package pe.gob.onpe.facade;

import java.util.List;
import java.util.logging.Level;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import pe.gob.onpe.ejb.LogUtil;
import pe.gob.onpe.ejb.ParticipacionListaCandidatos;
import pe.gob.onpe.ejb.Voto;
import pe.gob.onpe.ejb.id.VotoId;
import pe.gob.onpe.facade.local.VotoFacadeLocal;
import pe.gob.onpe.facade.remote.VotoFacadeRemote;


/**
 * Facade for entity Voto.
 * 
 * @see pe.gob.onpe.ejb.Voto
 * @author MyEclipse Persistence Tools
 */
@Stateless
public class VotoFacade implements VotoFacadeLocal, VotoFacadeRemote {
	// property constants

	@PersistenceContext
	private EntityManager entityManager;

	/**
	 * Perform an initial save of a previously unsaved Voto entity. All
	 * subsequent persist actions of this entity should use the #update()
	 * method.
	 * 
	 * @param entity
	 *            Voto entity to persist
	 * @throws RuntimeException
	 *             when the operation fails
	 */
	public void save(Voto entity) {
		LogUtil.log("saving Voto instance", Level.INFO, null);
		try {
			entityManager.persist(entity);
			LogUtil.log("save successful", Level.INFO, null);
		} catch (RuntimeException re) {
			LogUtil.log("save failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Delete a persistent Voto entity.
	 * 
	 * @param entity
	 *            Voto entity to delete
	 * @throws RuntimeException
	 *             when the operation fails
	 */
	public void delete(Voto entity) {
		LogUtil.log("deleting Voto instance", Level.INFO, null);
		try {
			entity = entityManager.getReference(Voto.class, entity.getId());
			entityManager.remove(entity);
			LogUtil.log("delete successful", Level.INFO, null);
		} catch (RuntimeException re) {
			LogUtil.log("delete failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Persist a previously saved Voto entity and return it or a copy of it to
	 * the sender. A copy of the Voto entity parameter is returned when the JPA
	 * persistence mechanism has not previously been tracking the updated
	 * entity.
	 * 
	 * @param entity
	 *            Voto entity to update
	 * @returns Voto the persisted Voto entity instance, may not be the same
	 * @throws RuntimeException
	 *             if the operation fails
	 */
	public Voto update(Voto entity) {
		LogUtil.log("updating Voto instance", Level.INFO, null);
		try {
			Voto result = entityManager.merge(entity);
			LogUtil.log("update successful", Level.INFO, null);
			return result;
		} catch (RuntimeException re) {
			LogUtil.log("update failed", Level.SEVERE, re);
			throw re;
		}
	}

	public Voto findById(VotoId id) {
		LogUtil.log("finding Voto instance with id: " + id, Level.INFO, null);
		try {
			Voto instance = entityManager.find(Voto.class, id);
			return instance;
		} catch (RuntimeException re) {
			LogUtil.log("find failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Find all Voto entities with a specific property value.
	 * 
	 * @param propertyName
	 *            the name of the Voto property to query
	 * @param value
	 *            the property value to match
	 * @param rowStartIdxAndCount
	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
	 *            row index in the query result-set to begin collecting the
	 *            results. rowStartIdxAndCount[1] specifies the the maximum
	 *            number of results to return.
	 * @return List<Voto> found by query
	 */
	@SuppressWarnings("unchecked")
	public List<Voto> findByProperty(String propertyName, final Object value,
			final int... rowStartIdxAndCount) {
		LogUtil.log("finding Voto instance with property: " + propertyName
				+ ", value: " + value, Level.INFO, null);
		try {
			final String queryString = "select model from Voto model where model."
					+ propertyName + "= :propertyValue";
			Query query = entityManager.createQuery(queryString);
			query.setParameter("propertyValue", value);
			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
				if (rowStartIdx > 0) {
					query.setFirstResult(rowStartIdx);
				}

				if (rowStartIdxAndCount.length > 1) {
					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
					if (rowCount > 0) {
						query.setMaxResults(rowCount);
					}
				}
			}
			return query.getResultList();
		} catch (RuntimeException re) {
			LogUtil.log("find by property name failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Find all Voto entities.
	 * 
	 * @param rowStartIdxAndCount
	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
	 *            row index in the query result-set to begin collecting the
	 *            results. rowStartIdxAndCount[1] specifies the the maximum
	 *            count of results to return.
	 * @return List<Voto> all Voto entities
	 */
	@SuppressWarnings("unchecked")
	public List<Voto> findAll(final int... rowStartIdxAndCount) {
		LogUtil.log("finding all Voto instances", Level.INFO, null);
		try {
			final String queryString = "select model from Voto model";
			Query query = entityManager.createQuery(queryString);
			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
				if (rowStartIdx > 0) {
					query.setFirstResult(rowStartIdx);
				}

				if (rowStartIdxAndCount.length > 1) {
					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
					if (rowCount > 0) {
						query.setMaxResults(rowCount);
					}
				}
			}
			return query.getResultList();
		} catch (RuntimeException re) {
			LogUtil.log("find all failed", Level.SEVERE, re);
			throw re;
		}
	}

	public void registrarVoto(VotoId votoId, ParticipacionListaCandidatos participacionListaCandidatos) {
		try{
			Voto  voto = new Voto();
			voto.setId(votoId);
			//voto.setParticipacionListaCandidatos(participacionListaCandidatos);
			entityManager.persist(voto);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Long cantidadVotosPorProceso(Long procesoElectoralId) {
		String consulta = "SELECT COUNT(*) FROM Voto u WHERE u.id.procesoElectoralId = :procesoElectoralId ";
		Query query = entityManager.createQuery(consulta);
		query.setParameter("procesoElectoralId", procesoElectoralId);
		Long cantidad =  (Long) query.getSingleResult();
		return cantidad;
	}

	public Long cantidadVotosPorTipoEleccion(Long procesoElectoralId, Long tipoEleccionId) {
		String consulta = "SELECT COUNT(*) FROM Voto u WHERE u.id.procesoElectoralId = :procesoElectoralId and u.id.tipoEleccionId = :tipoEleccionId ";
		Query query = entityManager.createQuery(consulta);
		
		query.setParameter("procesoElectoralId", procesoElectoralId);
		query.setParameter("tipoEleccionId",tipoEleccionId);
		
		Long cantidad =  (Long) query.getSingleResult();
		return cantidad;
	}
}